﻿/* 2014/4/6 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Cosmos.IO.FileSystemOperation
{
    /// <summary>
    /// Provides file system operations by invoking .Net API.
    /// </summary>
    public class FileSystemOperator : IFileSystemOperator
    {
        /*
                public bool Rename(string srcPath, string dstPath)
                {
                    bool isSuccessful = false;
                    if (File.Exists(srcPath) && ValidatePath(dstPath))
                    {
                        try
                        {
                            File.Move(srcPath, dstPath);
                            isSuccessful = true;
                        }
                        catch (Exception)
                        {
                            isSuccessful = false;
                        }
                    }
                    else if (Directory.Exists(srcPath) && ValidatePath(dstPath))
                    {
                        try
                        {
                            Directory.Move(srcPath, dstPath);
                            isSuccessful = true;
                        }
                        catch (Exception)
                        {
                            isSuccessful = false;
                        }
                    }
                    return isSuccessful;
                }

                public bool Move(string srcPath, string dstDirectoryPath)
                {
                    string srcName = Path.GetFileName(srcPath);
                    string dstPath = Path.Combine(dstDirectoryPath, srcName);
                    bool isSuccessful = false;
                    if (File.Exists(srcPath) && ValidatePath(dstPath))
                    {
                        try
                        {
                            File.Move(srcPath, dstPath);
                            isSuccessful = true;
                        }
                        catch (Exception)
                        {
                            isSuccessful = false;
                        }
                    }
                    else if (Directory.Exists(srcPath) && ValidatePath(dstPath))
                    {
                        try
                        {
                            Directory.Move(srcPath, dstPath);
                            isSuccessful = true;
                        }
                        catch (Exception)
                        {
                            isSuccessful = false;
                        }
                    }

                    return isSuccessful;
                }

                public bool Move(IEnumerable<string> srcPaths, string dstDirectoryPath)
                {
                    bool isSuccessful = true;
                    foreach (string srcPath in srcPaths)
                    {
                        if (!Move(srcPath, dstDirectoryPath))
                            isSuccessful = false;
                    }
                    return isSuccessful;
                }

                public bool Copy(string srcPath, string dstDirectoryPath)
                {
                    string srcName = Path.GetFileName(srcPath);
                    string dstPath = Path.Combine(dstDirectoryPath, srcName);
                    bool isSucceeful = false;
                    if (File.Exists(srcPath) && ValidatePath(dstPath))
                    {
                        try
                        {
                            File.Copy(srcPath, dstPath);
                            isSucceeful = true;
                        }
                        catch (Exception)
                        {
                            isSucceeful = false;
                        }
                    }
                    else if (Directory.Exists(srcPath) && ValidatePath(dstPath))
                    {
                        try
                        {
                            DirectoryInfo dstDirectory = Directory.CreateDirectory(dstPath);
                            DirectoryInfo srcDirectory = new DirectoryInfo(srcPath);
                            foreach (FileSystemInfo info in srcDirectory.GetFileSystemInfos())
                            {
                                Copy(info.FullName, dstPath);
                            }
                        }
                        catch (Exception)
                        {
                            isSucceeful = false;
                        }
                    }
                    return isSucceeful;
                }

                public bool Copy(IEnumerable<string> srcPaths, string dstDirectoryPath)
                {
                    bool isSuccessful = true;
                    foreach (string srcPath in srcPaths)
                    {
                        if (!Copy(srcPath, dstDirectoryPath))
                            isSuccessful = false;
                    }
                    return isSuccessful;
                }

                public bool Delete(string srcPath)
                {
                    bool isSuccessful = false;
                    if (File.Exists(srcPath))
                    {
                        try
                        {
                            File.Delete(srcPath);
                            isSuccessful = true;
                        }
                        catch (Exception)
                        {
                            isSuccessful = false;
                        }
                    }
                    else if (Directory.Exists(srcPath))
                    {
                        try
                        {
                            Directory.Delete(srcPath);
                            isSuccessful = true;
                        }
                        catch (Exception)
                        {
                            isSuccessful = false;
                        }
                    }
                    return isSuccessful;
                }

                public bool Delete(IEnumerable<string> srcPaths)
                {
                    bool isSuccessful = true;
                    foreach (string srcPath in srcPaths)
                    {
                        if (!Delete(srcPath))
                            isSuccessful = false;
                    }
                    return isSuccessful;
                }

                protected bool ValidatePath(string dstPath)
                {
                    return !File.Exists(dstPath) && !Directory.Exists(dstPath);
                }
        */

        private bool _overwriteCopy = false;

        private bool _recursiveDelete = true;

        public void Rename(string srcPath, string dstPath)
        {
            if (srcPath == null || dstPath == null)
                throw new ArgumentNullException();

            if (File.Exists(srcPath))
            {
                File.Move(srcPath, dstPath);
            }
            else if (Directory.Exists(srcPath))
            {
                Directory.Move(srcPath, dstPath);
            }
            else
            {
                throw new ArgumentException("Source path does not exist.");
            }
        }

        public void Move(string srcPath, string dstDirectoryPath)
        {
            if (srcPath == null || dstDirectoryPath == null)
                throw new ArgumentNullException();

            string srcName = Path.GetFileName(srcPath);
            string dstPath = Path.Combine(dstDirectoryPath, srcName);
            if (File.Exists(srcPath))
            {
                File.Move(srcPath, dstPath);
            }
            else if (Directory.Exists(srcPath))
            {
                Directory.Move(srcPath, dstPath);
            }
            else
            {
                throw new ArgumentException("Source path does not exist.");
            }
        }

        public void Move(IEnumerable<string> srcPaths, string dstDirectoryPath)
        {
            if (srcPaths == null || dstDirectoryPath == null)
                throw new ArgumentNullException();

            foreach (string srcPath in srcPaths)
            {
                Move(srcPath, dstDirectoryPath);
            }
        }

        public void Copy(string srcPath, string dstDirectoryPath)
        {
            if (srcPath == null || dstDirectoryPath == null)
                throw new ArgumentNullException();

            string srcName = Path.GetFileName(srcPath);
            string dstPath = Path.Combine(dstDirectoryPath, srcName);
            if (File.Exists(srcPath))
            {
                File.Copy(srcPath, dstPath, _overwriteCopy);
            }
            else if (Directory.Exists(srcPath))
            {
                if (!File.Exists(dstPath) && !Directory.Exists(dstPath))
                {
                    DirectoryInfo dstDirectory = Directory.CreateDirectory(dstPath);
                }
                
                DirectoryInfo srcDirectory = new DirectoryInfo(srcPath);
                foreach (FileSystemInfo info in srcDirectory.GetFileSystemInfos())
                {
                    Copy(info.FullName, dstPath);
                }
            }
            else
            {
                throw new ArgumentException("Source path does not exist.");
            }
        }

        public void Copy(IEnumerable<string> srcPaths, string dstDirectoryPath)
        {
            if (srcPaths == null || dstDirectoryPath == null)
                throw new ArgumentNullException();

            foreach (string srcPath in srcPaths)
            {
                Copy(srcPath, dstDirectoryPath);
            }
        }

        public void Delete(string srcPath)
        {
            if (srcPath == null)
                throw new ArgumentNullException();

            if (File.Exists(srcPath))
            {
                File.Delete(srcPath);
            }
            else if (Directory.Exists(srcPath))
            {
                Directory.Delete(srcPath, _recursiveDelete);
            }
            else
            {
                throw new ArgumentException("Source path does not exist.");
            }
        }

        public void Delete(IEnumerable<string> srcPaths)
        {
            if (srcPaths == null)
                throw new ArgumentNullException();

            foreach (string srcPath in srcPaths)
            {
                Delete(srcPath);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether allow
        /// to overwrite the file of the same name when
        /// copies file. Default value is false.
        /// </summary>
        public bool OverwriteCopy
        {
            get { return _overwriteCopy; }
            set { _overwriteCopy = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether to
        /// delete any subdirectories and files
        /// when deletes directory. Default value is true.
        /// </summary>
        public bool RecursiveDelete
        {
            get { return _recursiveDelete; }
            set { _recursiveDelete = value; }
        }
    }
}
